<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * 订单信息汇总数据模型
 * 
 * @author: wangxb
 * @email : wangxiaobo@parkingwang.com
 * @date  : 2018-01-06 15:47:44
 */
class DateCollection extends Model
{
    // 模型数据库表
    protected $table = 'date_collection';
    protected $primaryKey = 'id';

    public $guarded=[];
    
    protected $dates = [
        'hour',
        'create_at',
        'update_at'
    ];

    /**
     * 时间范围 作用域
     *
     * @param [type] $query
     * @param array $hour_struct
     * @return void
     */
    public function scopeRangeHour($query, array $hour_struct)
    {
        if([0] == '(' && $hour_struct[3] == ')'){
            $left  = '>';
            $right = '<';
        }elseif($hour_struct[0] == '(' && $hour_struct[3] == ']'){
            $left  = '>';
            $right = '<=';
        }elseif($hour_struct[0] == '[' && $hour_struct[3] == ')'){
            $left  = '>=';
            $right = '<';
        }else{
            $left  = '>=';
            $right = '<';
        }

        return $query->where('hour', $left, $hour_struct[1])
                     ->where('hour', $right, $hour_struct[2]);
    }

    /**
     * 车场范围 作用域
     *
     * @param [type] $query
     * @param [type] $park_codes
     * @return void
     */
    public function scopePark($query, $park_codes)
    {
        return $query->whereIn('park_code', $park_codes);
    }

    /**
     * 车场分组 作用域
     *
     * @param [type] $query
     * @return void
     */
    public function scopeGroupByPark($query)
    {
        return $query->groupBy('park_code');
    }

    /**
     * 查询总金额 和 总笔数
     *
     * @param [type] $query
     * @return void
     */
    public function collectIncome($park_codes, $date_struct)
    {
        $selects = '
            park_code, 
            (SUM(wechat_count)+SUM(alipay_count)+SUM(union_count)+SUM(cash_count)+SUM(etc_count)+SUM(other_count)) AS total_count,
            (SUM(wechat_amount)+SUM(alipay_amount)+SUM(union_amount)+SUM(cash_amount)+SUM(etc_amount)+SUM(other_amount)) AS total_amount
        ';
        $res = $this->park($park_codes)
                    ->rangeHour($date_struct)
                    ->groupByPark()
                    ->selectRaw($selects)
                    ->get();

        $re_park_codes = array_flip($park_codes);
        foreach ($res as &$val) {
            $val->sort_by = isset($val->park_code)?$re_park_codes[$val->park_code]:'';
        }

        $res = $res->sortBy("sort_by");
        return $res->prepend([
            'park_code' => 'heji',
            'total_count' => $res->sum('total_count'),
            'total_amount' => $res->sum('total_amount')
        ]);
    }

    /**
     * 汇总 支付方式维度数据
     *
     * @param [type] $park_codes
     * @param [type] $date_struct
     * @return void
     */
    public function collectPayType($park_codes, $date_struct)
    {
        $selects = '
        park_code, 
        SUM(wechat_count) AS wechat_count, SUM(wechat_amount) AS wechat_amount, 
        SUM(alipay_count) AS alipay_count, SUM(alipay_amount) AS alipay_amount, 
        SUM(cash_count) AS cash_count, SUM(cash_amount) AS cash_amount, 
        SUM(union_count) AS union_count, SUM(union_amount) AS union_amount,
        SUM(etc_count) AS etc_count, SUM(etc_amount) AS etc_amount, 
        SUM(other_count) AS other_count, SUM(other_amount) AS other_amount
        ';
        $res = $this->park($park_codes)
                    ->rangeHour($date_struct)
                    ->groupByPark()
                    ->selectRaw($selects)
                    ->get();
        $re_park_codes = array_flip($park_codes);
        foreach ($res as &$val) {
            $val->sort_by = isset($val->park_code)?$re_park_codes[$val->park_code]:'';
        }
        $res = $res->sortBy("sort_by");
        return $res->prepend([
            'park_code' => 'heji',
            'wechat_count'  => $res->sum('wechat_count'),
            'wechat_amount' => $res->sum('wechat_amount'),
            'alipay_count'  => $res->sum('alipay_count'),
            'alipay_amount' => $res->sum('alipay_amount'),
            'cash_count'    => $res->sum('cash_count'),
            'cash_amount'   => $res->sum('cash_amount'),
            'union_count'   => $res->sum('union_count'),
            'union_amount'  => $res->sum('union_amount'),
            'etc_count'     => $res->sum('etc_count'),
            'etc_amount'    => $res->sum('etc_amount'),
            'other_count'   => $res->sum('other_count'),
            'other_amount'  => $res->sum('other_amount')
        ]);

    }

    /**
     * 汇总 车辆类型维度数据
     *
     * @param [type] $park_codes
     * @param [type] $date_struct
     * @return void
     */
    public function collectCarType($park_codes, $date_struct)
    {
        $selects = collect($this->genFieldName(1))->map(function($value, $item){
            $fields = array_map(function($v){
                return 'SUM(' . $v . ')';
            }, $value);
            return implode('+', $fields) . ' AS ' . $item;
        })->push('park_code')->implode(',');

        $res = $this->park($park_codes)
                    ->rangeHour($date_struct)
                    ->groupByPark()
                    ->selectRaw($selects)
                    ->get();
        $re_park_codes = array_flip($park_codes);
        foreach ($res as &$val) {
            $val->sort_by = isset($val->park_code)?$re_park_codes[$val->park_code]:'';
        }
        $res = $res->sortBy("sort_by");
        return $res->prepend([ // 合计
            'park_code'    => 'heji',
            'car_count'    => $res->sum('car_count'),
            'car_amount'   => $res->sum('car_amount'),
            'truck_count'  => $res->sum('truck_count'),
            'truck_amount' => $res->sum('truck_amount'),
            'taxi_count'   => $res->sum('taxi_count'),
            'taxi_amount'  => $res->sum('taxi_amount'),
            'other_count'  => $res->sum('other_count'),
            'other_amount' => $res->sum('other_amount')
        ]);
    }


    private function genFieldName($flag = 0)
    {
        $car_type = config('custom.car_type');
        $pay_type = config('custom.pay_type');

        $names = collect($car_type)->map(function($value, $item) use ($pay_type){
            $counts  = [];
            $amounts = [];
            foreach($pay_type as $k=>$v){
                $counts[]  = sprintf('%s_%s_count', $item, $k);
                $amounts[] = sprintf('%s_%s_amount', $item, $k);
            }
            return [
                sprintf('%s_count', $item) => $counts,
                sprintf('%s_amount', $item) => $amounts
            ];
        });

        if($flag == 1){
            $ret = [];
            $names->map(function($value, $item) use (&$ret){
                foreach($value as $k=>$v){
                    $ret[$k] = $v;
                }
            });
            return $ret;
        }else{
            return $names->all();
        }
    }
}
